package com.briup.jd2511.jd2511bookstore.aspect;

import com.alibaba.fastjson.JSON;
import com.briup.jd2511.jd2511bookstore.annotation.SystemLog;
import com.briup.jd2511.jd2511bookstore.mapper.LogMapper;
import com.briup.jd2511.jd2511bookstore.pojo.Log;
import com.briup.jd2511.jd2511bookstore.utils.JwtUtil;
import io.jsonwebtoken.Claims;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;

@Component
@Aspect
@Slf4j
public class LogAspect {
    // 开始时间
    private long startTime;
    // 结束时间
    private long endTime;
    // 请求对象
    @Autowired
    private HttpServletRequest request;
    // 日志mapper
    @Autowired
    private LogMapper logMapper;

    // 定义切入点
    @Pointcut("@annotation(com.briup.jd2511.jd2511bookstore.annotation.SystemLog)")
    public void pc(){}

    // 定义环绕通知
    @Around("pc()")
    public Object logRecord(ProceedingJoinPoint joinPoint) throws Throwable {
        // 创建日志对象
        Log log = new Log();
        // 在目标方法执行前获取一些信息
        handleBefore(joinPoint, log);
        Object proceed = joinPoint.proceed();
        // 执行后获取日志的创建时间，耗时，结果的json格式
        handleAfter(proceed, log);
        // 插入到数据库中
        logMapper.insert(log);
        return proceed;
    }

    private void handleBefore(ProceedingJoinPoint joinPoint, Log log) {
        // 记录开始时间
        startTime = System.currentTimeMillis();
        // 当前用户，从jwt中获取
        String token = request.getHeader("token");
        Claims claims = JwtUtil.parseJWT(token);
        String username = (String) claims.get("username");
        log.setUsername(username);

        // 业务名称，从注解中的属性中获取（后面可以封装成方法）
        SystemLog systemLog = getSystemLog(joinPoint);
        String businessName = systemLog.businessName();
        log.setBusinessName(businessName);

        // 请求url、请求方式
        String url = request.getRequestURL().toString();
        log.setRequestUrl(url);
        String requestMethod = request.getMethod();
        log.setRequestMethod(requestMethod);

        // 目标类全类型名、目标方法名、请求参数列表
        String className = joinPoint.getSignature().getDeclaringTypeName();
        log.setClassPath(className);
        String methodName = joinPoint.getSignature().getName();
        log.setMethodName(methodName);
        Object[] args = joinPoint.getArgs();
        // 参数的格式需要转换成json
        String paramsJson = JSON.toJSONString(args);
        log.setParamsJson(paramsJson);
    }

    private void handleAfter(Object result, Log log) {
        String resultJson = JSON.toJSONString(result);
        log.setResultJson(resultJson);
        endTime = System.currentTimeMillis();
        log.setSpendTime(endTime - startTime);
        log.setCreateTime(LocalDateTime.now());
    }

    private SystemLog getSystemLog(ProceedingJoinPoint joinPoint) {
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        return signature.getMethod().getAnnotation(SystemLog.class);
    }
}
